package cn.maihe.elg.operation.centers.hymake.auth;

import cn.hutool.crypto.digest.MD5;
import cn.maihe.elg.operation.centers.hymake.config.HyMakeInfoConfig;
import cn.maihe.elg.operation.common.auth.Authorization;
import cn.maihe.elg.operation.config.ElgAuthConfig;
import cn.maihe.elg.operation.utils.ElgLogger;
import cn.maihe.elg.operation.utils.SM3Util;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.util.Assert;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * @Description 海迈签名验签算法
 * @Author WJH
 * @Date 2021/07/12
 */
@Slf4j
public class HyMakeAuthorization implements Authorization {
    private final ElgAuthConfig elgAuthConfig;
    private final HyMakeInfoConfig.CenterInfo centerInfo;

    public HyMakeAuthorization(ElgAuthConfig elgAuthConfig, HyMakeInfoConfig.CenterInfo centerInfo) {
        this.elgAuthConfig = elgAuthConfig;
        this.centerInfo = centerInfo;

        Assert.hasText(elgAuthConfig.getPubKey(), () -> "elg系统公钥不能为空");
        Assert.hasText(elgAuthConfig.getPriKey(), () -> "elg系统私钥不能为空");

        Assert.hasText(centerInfo.getAppId(), () -> centerInfo + "的appId不能为空");
        Assert.hasText(centerInfo.getSlat(), () -> centerInfo + "的slat不能为空");
        Assert.hasText(centerInfo.getSm2PriKey(), () -> centerInfo + "的sm2PriKey不能为空");
        Assert.hasText(centerInfo.getSm2PubKey(), () -> centerInfo + "的sm2PubKey不能为空");

    }

    @Override
    public String signature(Object body, String timestamp) {
        return null;
    }

    @Override
    public boolean verifySignature(Object reqBody, String signedMsg, String timestamp) {
        return false;
    }

    public String signature(String requestId, String clearBizReqJsonBody, String timestamp) {
        /**采用32位MD5算法（大写）计算获得，sign=MD5(appId + requestId + slat + timeStamp + BASE64_ENC(httpbody))*/

        String messageDigest = this.buildMessageDigest(requestId, clearBizReqJsonBody, timestamp);
        ElgLogger.debug(log, l -> l.debug("待签名字符串：{}", messageDigest));
        String signed = MD5.create().digestHex(messageDigest).toUpperCase();
        ElgLogger.debug(log, l -> l.debug("签名后字符串：{}", signed));

        return signed;
    }

    public boolean verifySignature(String requestId, String clearBizReqJsonBody, String signedMsg, String timestamp) {

        String messageDigest = this.buildMessageDigest(requestId, clearBizReqJsonBody, timestamp);
        ElgLogger.debug(log, l -> l.debug("签名摘要信息：{}", messageDigest));

        String signed = MD5.create().digestHex(messageDigest).toUpperCase();
        ElgLogger.debug(log, l -> l.debug("签名后字符串：{}", signed));
        boolean verifyTF = signed.equalsIgnoreCase(signedMsg);
        ElgLogger.debug(log, l -> l.debug("验签结果：[{}]", verifyTF));

        return verifyTF;
    }

    /**
     * @param requestId
     * @param clearBizReqJsonBody 业务明文json字符串
     * @param timestamp
     * @return
     */
    String buildMessageDigest(String requestId, String clearBizReqJsonBody, String timestamp) {
        String b64EncodeReqBody = Base64.encodeBase64String(clearBizReqJsonBody.getBytes(StandardCharsets.UTF_8));
        String messageDigest = String.format("%s%s%s%s%s", centerInfo.getAppId(), requestId, centerInfo.getSlat(), timestamp, b64EncodeReqBody);
        return messageDigest;
    }


    /**
     * 厦门 参数加签
     *
     * @return
     */
    public String mockSignature(Map<String, Object> params) {
        return mockSignature(params, new HashMap<>());
    }

    public String mockSignature(Map<String, Object> params, Map<String, Object> ignore) {

        String messageDigest = buildMessageDigest(params, centerInfo.getBhAppKey(), ignore);
        ElgLogger.debug(log, l -> l.debug("签名摘要信息：{}", messageDigest));

        String signature = MD5.create().digestHex(messageDigest).toUpperCase();
        ElgLogger.debug(log, l -> l.debug("签名后字符串：{}", signature));

        return signature;
    }

    /**
     * 厦门 测试模拟参数加签
     *
     * @return
     */
    public String signature(Map<String, Object> params) {
        return signature(params, new HashMap<>());
    }

    public String signature(Map<String, Object> params, Map<String, Object> ignore) {

        String messageDigest = buildMessageDigest(params, centerInfo.getSlat(), ignore);
        ElgLogger.debug(log, l -> l.debug("签名摘要信息：{}", messageDigest));

        String signature = MD5.create().digestHex(messageDigest).toUpperCase();
        ElgLogger.debug(log, l -> l.debug("签名后字符串：{}", signature));

        return signature;
    }

    /**
     * 厦门 参数验签
     *
     * @return
     */
    public boolean verifySignature(Map<String, Object> params, String sinature, Map<String, Object> ignore) {

        String messageDigest = buildMessageDigest(params, centerInfo.getBhAppKey(), ignore);
        ElgLogger.debug(log, l -> l.debug("签名摘要信息：{}", messageDigest));

        String signed = MD5.create().digestHex(messageDigest).toUpperCase();
        ElgLogger.debug(log, l -> l.debug("签名后字符串：{}", signed));
        boolean verifyTF = signed.equalsIgnoreCase(sinature);
        ElgLogger.debug(log, l -> l.debug("验签结果：[{}]", verifyTF));

        return verifyTF;
    }

    /**
     * 拼接签名：a=b&c=d
     *
     * @return
     */
    public static String buildMessageDigest(Map<String, Object> params, String key, Map<String, Object> ignore) {
        // 第一步：参数名ASCII码从小到大排序（字典序）,这里可能由于不同工具转换的JSON格式，导致验签失败
        Map<String, Object> sortedParams = new TreeMap<>(params);

        // 创建StringBuilder来构建签名字符串
        StringBuilder stringA = new StringBuilder();

        // 遍历排序后的参数
        boolean first = true;
        for (Map.Entry<String, Object> entry : sortedParams.entrySet()) {
            Object paramValue = entry.getValue();
            // 如果参数值为空，则不参与签名
            if (paramValue != null && !paramValue.toString().trim().isEmpty() && !ignore.containsKey(entry.getKey())) {
                if (first) {
                    first = false;
                } else {
                    stringA.append("&");
                }
                stringA.append(entry.getKey()).append("=").append(paramValue.toString().trim());
            }
        }
        // 第二步：拼接API密钥
        return stringA + "&key=" + key;
    }

    public static void main(String[] args) throws IOException {


        // JSON字符串
        String jsonStr = "{\"APPID\":\"A12345\",\"APPLY_ID\":\"AP20250210001\",\"SECRET_KEY\":\"secret123456\",\"APPLY_INFO\":{\"ORDER_NO\":\"ZB2025021001\",\"CREATE_TIME\":\"20250210142030\"},\"TENDER_INFO\":\"BG6MiZlxlnDfz0bOOfYIh8QOrydAJKEmDAe8fTT10q9mHTUFx4EdCutbAwG6IKUOcd8F/uZgn4wkNUaTbb6yB5HOZir69bB3K4mKT7zWQrX4cd169xGQztzxnIcV5TjcR3Mbqxpv8oGMAWk5GqK2vPMoEtB6Vuu8sn5RGAqCUgXgjCtYOTjEv4GvxLcd18DEGhOpYnko4HtEXM4zUMYvLH5g/rBrRrADmE3rAZECGhW/rKwxzm+C+YGanOxUDCUUKkoGBRpCoE/fzEQ2QtUWwZpc37GPe3cy+6H/JOml/eHVB4SrA0LkXTI0dCvOOkka5MC5br7p7ULh9bPzQEiey89jsov2TC1OU1KQzbI5WiVV8Sdox2RwllaoB3fbhukAc6tnNO0bOFGvi4XO1umcgM+34Qek2W5MtC8T/AK/khjFdIBhEJyi/cRSxjoBBYTZCMWTCu8PhAft65Sh4T4I1c7GvXH3GjzIgJSYntQK8liM40fDqxQqhaEwU/JHGf94TlXsQbpUgb6nWb98kyplmLjBc4cA3SqwsPv1AMLD1u9BDoxxZWG8PHSjbqLBQq+LnhSJjQLKvQ32QIa+XOgFucAa9XIAZ8uNdrqJPkleRROMu1xUDBIcLWo3VbQ0/F7JTni4ckMMZUOMG+j0TuWZv8hxlXQb5WBv2UQqABd4aznhmhGzf04VlgxwmmNZ7rR3g4w9nIn1XyGO8ftsz0FmBjjv5oxzR2SNUmUyJRFMjcXnmn4S9Gnz2Y/6L7YqwKRGE6wvRqfRAMyMK+BidcdEL5vxGvD1prj3+a4PWNXdohda+g1ot1BYC+4Fwr4LOCqNBR04dk6txjNzdpGIDBm5C8BZ9Ua6wN6uDHuVd55JYNifFdWhEqjh+UtMEO8CmO/Clyurs6+h+n1XlDmzp1JE0maqX6/TWF4VJDKBfsZO8cmkva2ximXtk+ABmj3le6UMVwwjFsOR9YslFUox4N0FEaxAURegAAcaKLLlPIVy362fzzijvraCZArf21+m7W5ieeu8xgCkJYTevkfTnFCrtEvCj0J1lqYcIs3MY6KWaqLQJpOBAXRF7UNNLXElQ/aj3zphv0HgF1V6oSYOIl18DW2BpWoR0nsrpHTFtQExJxdeGcZex9EvfDMBJeHLxhteYm1nQZMpLXHj4jCswEklNSVOy8iuipdVXzgkk9amwIOsWroK69OnbnFYSjPGtDuTPI6AJwvrU1Rnzn98xKJoi5I+KEOB6+nuNfnZTGroid4Su52FCfTuFaooUQwJ42ASm9y2xxJ6nEoXr9JjlWADVTfe6QqSGbZI/ZiP2NeOls5261IxOWaJGG0hesusWmGIhDKfqTUHQCi2WQ6RleWsB8CtVea0JJ1llxr6ZNaG/B5H99cBVJuydlMXj3Qa0UL+CMC0K1lgAEfw1FaZdJOB/xA/yNkJKWGtBs77A7xSRYpn6HVECMPdCrPHge+qWixtnlHmORisd91LhVmNxXVhrdS2RDhNcz4JKeBChf6CYYhF/dh/cXQM1ArhRrEknsLXHc8+Yyc6Bt+QjyMaa0nLozB7SprMj5r47EQ/aO1NoPq7KreMlu7bhNJUurEU/OywLen2IYXEVXqq/Z5e2g4bVR4FncNFon8QLLpIlCRVcS36XujUSR5cDOjVzyf3dePyYnYuz+cswVift2XveCipPHxwp+rpdfYSXxrSAPHs13RCjR/Uh6ys4TVmAjoAgq17E+Mmu+hIXnrl\",\"BIDDER\":{\"BIDDER_NAME\":\"工程建设有限公司\",\"BIDDER_CREDIT_CODE\":\"91110000MA002ABC\",\"BIDDER_CONTACT_NAME\":\"王强\",\"BIDDER_CONTACT_TEL\":\"13812345678\",\"BIDDER_CONTACT_IDCARD_TYPE\":\"身份证\",\"BIDDER_CONTACT_IDCARD\":\"110101198001010010\",\"BIDDER_ADDRESS\":\"北京市朝阳区望京东园\",\"BIDDER_EAMIL\":\"wangqiang@example.com\",\"LEGAL_PERSON_NAME\":\"张三\",\"LEGAL_PERSON_IDCARD\":\"110101197001010020\",\"LEGAL_PERSON_IDCARD_TYPE\":\"身份证\",\"LEGAL_PERSON_TEL\":\"13612345678\",\"BIDDER_BANK_TEL\":\"010-88888888\",\"V_JSON\":\"建筑工程施工一级资质\"},\"INVOICE\":{\"INVOICE_TYPE\":\"增值税专用发票\",\"COMPANY_NAME\":\"工程建设有限公司\",\"BIDDER_CODE\":\"91110000MA002ABC\",\"BANK_CODE\":\"6222020903007654321\",\"BANK_OPENBANK\":\"中国工商银行北京分行\",\"COMPANY_ADDRESS\":\"北京市朝阳区望京东园\",\"COMPANY_TEL\":\"010-65789012\",\"COMPANY_EMAIL\":\"invoice@example.com\",\"RECEIVE_NAME\":\"李四\",\"RECEIVE_TEL\":\"13612349876\",\"RECEIVE_ADDRESS\":\"北京市海淀区中关村2号\"},\"GUARANTOR_CREDIT_CODE\":\"91110000MA003DEF\",\"GUARANTOR_NAME\":\"担保有限公司\",\"TIMESTAMP\":\"20250210142030\",\"SIGNATURE\":\"\"}";

        // 使用ObjectMapper解析JSON
        ObjectMapper mapper = new ObjectMapper();
//        Map<String, Object> jsonMap = mapper.readValue(jsonStr, Map.class);
        Map<String, Object> jsonMap = JSONObject.parseObject(jsonStr, Map.class);

        // 构造参数Map（只取顶层字段）
        Map<String, Object> params = new HashMap<>();
        params.put("APPID", jsonMap.get("APPID"));
        params.put("APPLY_ID", jsonMap.get("APPLY_ID"));
        params.put("SECRET_KEY", jsonMap.get("SECRET_KEY"));

        params.put("APPLY_INFO", jsonMap.get("APPLY_INFO"));
        params.put("TENDER_INFO", jsonMap.get("TENDER_INFO"));
        params.put("INVOICE", jsonMap.get("INVOICE"));
        params.put("BIDDER", jsonMap.get("BIDDER"));

        params.put("GUARANTOR_CREDIT_CODE", jsonMap.get("GUARANTOR_CREDIT_CODE"));
        params.put("GUARANTOR_NAME", jsonMap.get("GUARANTOR_NAME"));
        params.put("TIMESTAMP", jsonMap.get("TIMESTAMP"));
        params.put("SIGNATURE", jsonMap.get("SIGNATURE"));

        params.put("a", "");
        params.put("A", "");
        params.put("b", "");
        params.put("c", "");
        params.put("d", "");


        Map<String, Object> ignore = new HashMap<>();
        ignore.put("APPID", null);

        // API密钥
        String key = "00B95AE4A5F81DBC603C9BF6C11380C971C391BD797938C53296016ACD687223F9"; // 替换为实际的API密钥

        // 生成签名
        String signature = buildMessageDigest(params, key, new HashMap<>());
        String signature2 = buildMessageDigest(params, key,ignore);
        System.out.println("Generated Signature: " + signature);

        // 打印最终数据
        String signed = MD5.create().digestHex(signature).toUpperCase();
        String signed2 = MD5.create().digestHex(signature2).toUpperCase();
        System.out.println("Signature: " + signed);


        // 将签名添加到原始参数中
        params.put("SIGNATURE", signature);

    }

    /**
     * 采用SM3算法（大写）计算获得，sign=SM3(appId + requestId + slat + timeStamp + httpbody)
     * slat由平台分配
     *
     * @param requestId
     * @param clearBizReqJsonBody
     * @param timestamp
     * @return
     */
    public String signatureSM3(String requestId, String clearBizReqJsonBody, String timestamp) {
        String messageDigest = this.buildMessageDigestSM3(requestId, clearBizReqJsonBody, timestamp);
        ElgLogger.debug(log, l -> l.debug("待签名字符串：{}", messageDigest));
        String signed = SM3Util.hash(messageDigest).toUpperCase();
//        String signed = MD5.create().digestHex(messageDigest).toUpperCase();
        ElgLogger.debug(log, l -> l.debug("签名后字符串：{}", signed));

        return signed;
    }

    /**
     * 采用SM3算法（大写）计算获得，sign=SM3(appId + requestId + slat + timeStamp + httpbody)
     * slat由平台分配
     *
     * @param requestId
     * @param clearBizReqJsonBody
     * @param signedMsg
     * @param timestamp
     * @return
     */
    public boolean verifySignatureSM3(String requestId, String clearBizReqJsonBody, String signedMsg, String timestamp) {
        String messageDigest = this.buildMessageDigestSM3(requestId, clearBizReqJsonBody, timestamp);
        ElgLogger.debug(log, l -> l.debug("签名摘要信息：{}", messageDigest));
        String signed = SM3Util.hash(messageDigest).toUpperCase();
//        String signed = MD5.create().digestHex(messageDigest).toUpperCase();
        ElgLogger.debug(log, l -> l.debug("签名后字符串：{}", signed));
        boolean verifyTF = signed.equalsIgnoreCase(signedMsg);
        ElgLogger.debug(log, l -> l.debug("验签结果：[{}]", verifyTF));

        return verifyTF;
    }

    /**
     * @param requestId
     * @param clearBizReqJsonBody 业务明文json字符串
     * @param timestamp
     * @return
     */
    String buildMessageDigestSM3(String requestId, String clearBizReqJsonBody, String timestamp) {
//        String b64EncodeReqBody = Base64.encodeBase64String(clearBizReqJsonBody.getBytes(StandardCharsets.UTF_8));
        String messageDigest = String.format("%s%s%s%s%s", centerInfo.getAppId(), requestId, centerInfo.getSlat(), timestamp, clearBizReqJsonBody);
        return messageDigest;
    }


}
